//
//  IFlyRealTimeASRManager.swift
//  GLUZSwift
//
//  Created by AI Assistant on 2024/12/19.
//  Copyright © 2024 考拉🐨. All rights reserved.
//

import Foundation
import UIKit
import SocketRocket

// MARK: - 实时语音转写结果回调协议
protocol IFlyRealTimeASRDelegate: AnyObject {
    /// 识别结果回调
    /// - Parameters:
    ///   - result: 识别结果文本
    ///   - isLast: 是否为最后一个结果
    func realTimeASRDidReceiveResult(_ result: String, isLast: Bool)
    
    /// 识别完成回调
    /// - Parameter error: 错误信息，nil表示成功
    func realTimeASRDidComplete(_ error: Error?)
    
    /// 开始识别回调
    func realTimeASRDidBegin()
    
    /// 停止识别回调
    func realTimeASRDidEnd()
    
    /// 连接状态变化回调
    /// - Parameter isConnected: 是否已连接
    func realTimeASRConnectionStateChanged(_ isConnected: Bool)
    
    /// 错误回调
    /// - Parameter error: 错误信息
    func realTimeASRDidFail(_ error: Error)
}

// MARK: - 实时语音转写语言枚举
enum IFlyRealTimeASRLanguage: String, CaseIterable {
    case chinese = "cn"
    case russian = "ru"
    
    var displayName: String {
        switch self {
        case .chinese:
            return "中文"
        case .russian:
            return "俄文"
        }
    }
}

// MARK: - 实时语音转写状态枚举
enum IFlyRealTimeASRState {
    case idle           // 空闲状态
    case connecting     // 连接中
    case connected      // 已连接
    case recognizing    // 识别中
    case error          // 错误状态
}

// MARK: - 实时语音转写工具类
class IFlyRealTimeASRManager: NSObject {
    
    // MARK: - 单例
    static let shared = IFlyRealTimeASRManager()
    
    // MARK: - 属性
    private var webSocket: SRWebSocket?
    var currentLanguage: IFlyRealTimeASRLanguage = .chinese
    private var currentState: IFlyRealTimeASRState = .idle
    private var isRecognizing = false
    
    // 科大讯飞配置参数（需要替换为实际的参数）
    private let appId: String = "15c74a67" // 请替换为实际的appId
    private let appKey: String = "11f26df64a54bb3e6bed674622a33c22" // 请替换为实际的appKey
    
    // WebSocket连接参数
    private let baseURL = "wss://rtasr.xfyun.cn/v1/ws"
    
    // 音频参数
    private let sampleRate: Int = 16000  // 采样率16kHz
    private let bitDepth: Int = 16       // 位深16bit
    private let channels: Int = 1        // 单声道
    private let chunkSize: Int = 1280    // 每40ms发送1280字节
    private let chunkInterval: TimeInterval = 0.04 // 40ms间隔
    
    // 重连相关
    private var reconnectCount = 0
    private let maxReconnectCount = 5
    private let reconnectInterval: TimeInterval = 2.0
    
    // MARK: - 回调
    weak var delegate: IFlyRealTimeASRDelegate?
    
    // MARK: - 初始化
    private override init() {
        super.init()
    }
    
    // MARK: - 公共方法
    
    /// 设置识别语言
    /// - Parameter language: 语言类型
    func setLanguage(_ language: IFlyRealTimeASRLanguage) {
        currentLanguage = language
        print("🔊 设置识别语言: \(language.displayName)")
    }
    
    /// 开始实时语音转写
    /// - Returns: 是否开始成功
    @discardableResult
    func startRealTimeASR() -> Bool {
        guard !isRecognizing else {
            print("⚠️ 实时语音转写正在进行中，请先停止当前识别")
            return false
        }
        
        guard currentState == .idle || currentState == .error else {
            print("⚠️ 当前状态不允许开始识别: \(currentState)")
            return false
        }
        
        // 检查配置参数
        guard !appId.isEmpty && !appKey.isEmpty else {
            let error = NSError(domain: "IFlyRealTimeASR", code: -1, userInfo: [NSLocalizedDescriptionKey: "请先配置appId和appKey"])
            delegate?.realTimeASRDidFail(error)
            return false
        }
        
        print("🔊 开始实时语音转写 - 语言: \(currentLanguage.displayName)")
        connectWebSocket()
        return true
    }
    
    /// 停止实时语音转写
    func stopRealTimeASR() {
        guard isRecognizing else {
            print("⚠️ 当前没有进行实时语音转写")
            return
        }
        
        print("🔊 停止实时语音转写")
        isRecognizing = false
        currentState = .idle
        
        // 发送结束标识
        sendEndSignal()
        
        // 关闭WebSocket连接
        closeWebSocket()
        
        delegate?.realTimeASRDidEnd()
    }
    
    /// 取消实时语音转写
    func cancelRealTimeASR() {
        print("🔊 取消实时语音转写")
        isRecognizing = false
        currentState = .idle
        
        // 停止重连
        stopReconnect()
        
        // 关闭WebSocket连接
        closeWebSocket()
        
        delegate?.realTimeASRDidEnd()
    }
    
    /// 发送音频数据
    /// - Parameter audioData: PCM格式的音频数据
    func sendAudioData(_ audioData: Data) {
        guard isRecognizing, currentState == .connected else {
            print("⚠️ 当前状态不允许发送音频数据: \(currentState)")
            return
        }
        
        guard let webSocket = webSocket, webSocket.readyState == .OPEN else {
            print("⚠️ WebSocket连接未建立")
            return
        }
        
        do {
            try webSocket.send(data: audioData)
        } catch {
            print("❌ 发送音频数据失败: \(error.localizedDescription)")
            delegate?.realTimeASRDidFail(error)
        }
    }
    
    /// 检查是否正在识别
    var isListening: Bool {
        return isRecognizing
    }
    
    /// 获取当前状态
    var state: IFlyRealTimeASRState {
        return currentState
    }
    
    // MARK: - 私有方法
    
    /// 连接WebSocket
    private func connectWebSocket() {
        currentState = .connecting
        
        // 生成签名参数
        let signaTuple = createSigna(appId: appId, appKey: appKey)
        let timestamp = signaTuple.0
        let signa = signaTuple.1
        
        print("🔊 生成签名参数 - timestamp: \(timestamp), signa: \(signa)")
        
        // 构建WebSocket URL - 与RTManager.m保持一致
        let urlString = "\(baseURL)?appid=\(appId)&ts=\(timestamp)&transStrategy=2&signa=\(signa)&lang=\(currentLanguage.rawValue)"
        
        guard let url = URL(string: urlString) else {
            let error = NSError(domain: "IFlyRealTimeASR", code: -2, userInfo: [NSLocalizedDescriptionKey: "构建WebSocket URL失败"])
            DispatchQueue.main.async { [weak self] in
                self?.delegate?.realTimeASRDidFail(error)
            }
            return
        }
        
        print("🔊 连接WebSocket: \(url.absoluteString)")
        
        // 在后台线程创建和连接WebSocket，避免主线程阻塞
        DispatchQueue.global(qos: .userInitiated).async { [weak self] in
            guard let self = self else { return }
            
            // 创建WebSocket连接
            self.webSocket = SRWebSocket(url: url)
            self.webSocket?.delegate = self
            
            // 在主线程打开连接
            DispatchQueue.main.async {
                self.webSocket?.open()
            }
        }
    }
    
    /// 关闭WebSocket连接
    private func closeWebSocket() {
        webSocket?.close()
        webSocket = nil
        currentState = .idle
    }
    
    /// 发送结束信号
    private func sendEndSignal() {
        // 发送空的音频数据表示结束
        let emptyData = Data()
        sendAudioData(emptyData)
    }
    
    /// 生成签名
    /// - Parameters:
    ///   - appId: 应用ID
    ///   - appKey: 应用密钥
    /// - Returns: (时间戳, 签名)
    private func createSigna(appId: String, appKey: String) -> (String, String) {
        // 获取当前时间戳（秒）- 与RTManager.m保持一致
        let timestamp = String(format: "%.0f", Date().timeIntervalSince1970)
        
        // 构建baseString - 与RTManager.m保持一致
        let baseString = appId + timestamp
        
        // 对baseString进行MD5加密 - 与RTManager.m保持一致
        let md5String = CryptoHelper.md5Hash(baseString)
        
        // 使用HMAC-SHA1加密并Base64编码 - 与RTManager.m保持一致
        let signa = CryptoHelper.hmacSHA1(md5String, key: appKey)
        
        print("🔊 签名生成调试信息（参考RTManager.m）:")
        print("  appId: \(appId)")
        print("  appKey: \(appKey)")
        print("  timestamp: \(timestamp)")
        print("  baseString: \(baseString)")
        print("  md5String: \(md5String)")
        print("  signa: \(signa)")
        
        return (timestamp, signa)
    }
    
    /// 开始重连
    private func startReconnect() {
        guard reconnectCount < maxReconnectCount else {
            print("❌ 重连次数超过最大限制，停止重连")
            let error = NSError(domain: "IFlyRealTimeASR", code: -3, userInfo: [NSLocalizedDescriptionKey: "重连失败，请检查网络连接"])
            DispatchQueue.main.async { [weak self] in
                self?.delegate?.realTimeASRDidFail(error)
            }
            return
        }
        
        reconnectCount += 1
        print("🔄 开始第\(reconnectCount)次重连，\(reconnectInterval)秒后重连")
        
        // 在后台线程执行重连，避免主线程阻塞
        DispatchQueue.global(qos: .userInitiated).asyncAfter(deadline: .now() + reconnectInterval) { [weak self] in
            self?.connectWebSocket()
        }
    }
    
    /// 停止重连
    private func stopReconnect() {
        // 重连现在使用 DispatchQueue，不需要手动停止
        // 重置重连计数
        reconnectCount = 0
    }
    
    /// 解析识别结果
    /// - Parameter jsonString: JSON字符串
    private func parseRecognitionResult(_ jsonString: String) {
        guard let jsonData = jsonString.data(using: .utf8),
              let jsonDict = try? JSONSerialization.jsonObject(with: jsonData) as? [String: Any] else {
            print("❌ 解析JSON失败: \(jsonString)")
            return
        }
        
        // 检查是否有错误
        if let errorCode = jsonDict["code"] as? Int, errorCode != 0 {
            let errorMessage = jsonDict["message"] as? String ?? "未知错误"
            let error = NSError(domain: "IFlyRealTimeASR", code: errorCode, userInfo: [NSLocalizedDescriptionKey: errorMessage])
            delegate?.realTimeASRDidFail(error)
            return
        }
        
        // 解析识别结果
        guard let cn = jsonDict["cn"] as? [String: Any],
              let st = cn["st"] as? [String: Any],
              let rt = st["rt"] as? [[String: Any]] else {
            print("❌ 解析识别结果结构失败")
            return
        }
        
        var resultText = ""
        var isLast = false
        
        // 检查是否为最后结果
        if let ed = st["ed"] as? String {
            isLast = (ed != "0") //
        }
        
        // 提取识别文本
        for rtItem in rt {
            if let ws = rtItem["ws"] as? [[String: Any]] {
                for wsItem in ws {
                    if let cw = wsItem["cw"] as? [[String: Any]] {
                        for cwItem in cw {
                            if let word = cwItem["w"] as? String,
                               let wp = cwItem["wp"] as? String {
                                // 过滤标点符号
                                if wp != "p" {
                                    resultText += word
                                }
                            }
                        }
                    }
                }
            }
        }
        
        if !resultText.isEmpty {
            print("🔊 识别结果: \(resultText), 是否最后结果: \(isLast)")
            delegate?.realTimeASRDidReceiveResult(resultText, isLast: isLast)
        }
    }
}

// MARK: - SRWebSocketDelegate
extension IFlyRealTimeASRManager: SRWebSocketDelegate {
    
    func webSocketDidOpen(_ webSocket: SRWebSocket) {
        print("✅ WebSocket连接成功")
        currentState = .connected
        isRecognizing = true
        reconnectCount = 0 // 重置重连计数
        
        delegate?.realTimeASRConnectionStateChanged(true)
        delegate?.realTimeASRDidBegin()
    }
    
    func webSocket(_ webSocket: SRWebSocket, didReceiveMessage message: Any) {
        guard let messageString = message as? String else {
            print("❌ 收到非字符串消息")
            return
        }
        
        print("🔊 收到WebSocket消息: \(messageString)")
        
        guard let jsonData = messageString.data(using: .utf8),
              let jsonDict = try? JSONSerialization.jsonObject(with: jsonData) as? [String: Any] else {
            print("❌ 解析WebSocket消息失败")
            return
        }
        
        // 处理不同类型的消息
        if let action = jsonDict["action"] as? String {
            switch action {
            case "started":
                print("✅ 握手成功，开始识别")
                if let sid = jsonDict["sid"] as? String {
                    print("🔊 会话ID: \(sid)")
                }
                
            case "result":
                // 处理识别结果
                if let data = jsonDict["data"] as? String {
                    parseRecognitionResult(data)
                }
                
            case "error":
                // 处理错误
                let errorCode = jsonDict["code"] as? Int ?? -1
                let errorMessage = jsonDict["message"] as? String ?? "未知错误"
                let error = NSError(domain: "IFlyRealTimeASR", code: errorCode, userInfo: [NSLocalizedDescriptionKey: errorMessage])
                print("❌ WebSocket错误: \(errorMessage)")
                delegate?.realTimeASRDidFail(error)
                
            default:
                print("🔊 收到未知action: \(action)")
            }
        }
    }
    
    func webSocket(_ webSocket: SRWebSocket, didCloseWithCode code: Int, reason: String?, wasClean: Bool) {
        print("🔊 WebSocket连接关闭 - code: \(code), reason: \(reason ?? "nil"), wasClean: \(wasClean)")
        
        currentState = .idle
        isRecognizing = false
        self.webSocket = nil
        
        delegate?.realTimeASRConnectionStateChanged(false)
        
        // 如果不是主动关闭，尝试重连
        if !wasClean && reconnectCount < maxReconnectCount {
            startReconnect()
        } else if wasClean {
            delegate?.realTimeASRDidComplete(nil)
        } else {
            let error = NSError(domain: "IFlyRealTimeASR", code: code, userInfo: [NSLocalizedDescriptionKey: reason ?? "连接异常关闭"])
            delegate?.realTimeASRDidFail(error)
        }
    }
    
    func webSocket(_ webSocket: SRWebSocket, didFailWithError error: Error) {
        print("❌ WebSocket连接失败: \(error.localizedDescription)")
        
        currentState = .error
        isRecognizing = false
        self.webSocket = nil
        
        delegate?.realTimeASRConnectionStateChanged(false)
        
        // 尝试重连
        startReconnect()
    }
}

// MARK: - 使用示例
extension IFlyRealTimeASRManager {
    
    /// 简单的使用示例
    func simpleUsageExample() {
        // 1. 设置代理
        IFlyRealTimeASRManager.shared.delegate = self
        
        // 2. 设置语言
        IFlyRealTimeASRManager.shared.setLanguage(.chinese)
        
        // 3. 开始识别
        IFlyRealTimeASRManager.shared.startRealTimeASR()
        
        // 4. 发送音频数据（需要从音频采集设备获取PCM数据）
        // let audioData = getPCMDataFromMicrophone()
        // IFlyRealTimeASRManager.shared.sendAudioData(audioData)
        
        // 5. 停止识别
        // IFlyRealTimeASRManager.shared.stopRealTimeASR()
    }
}

// MARK: - IFlyRealTimeASRDelegate 默认实现
extension IFlyRealTimeASRManager: IFlyRealTimeASRDelegate {
    
    func realTimeASRDidReceiveResult(_ result: String, isLast: Bool) {
        print("🔊 收到识别结果: \(result), 是否最后结果: \(isLast)")
    }
    
    func realTimeASRDidComplete(_ error: Error?) {
        if let error = error {
            print("❌ 识别完成，有错误: \(error.localizedDescription)")
        } else {
            print("✅ 识别完成，无错误")
        }
    }
    
    func realTimeASRDidBegin() {
        print("🔊 开始识别")
    }
    
    func realTimeASRDidEnd() {
        print("🔊 结束识别")
    }
    
    func realTimeASRConnectionStateChanged(_ isConnected: Bool) {
        print("🔊 连接状态变化: \(isConnected ? "已连接" : "已断开")")
    }
    
    func realTimeASRDidFail(_ error: Error) {
        print("❌ 识别失败: \(error.localizedDescription)")
    }
}
